package com.barryredmond.mileagecalc;

import java.util.Vector;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;

/**
 * <p>
 * The AboutScreen is a Canvas which shows the MTE Logo and some information
 * about the MTE
 * </p>
 * 
 * @author barryred
 */
public final class AboutScreen extends Canvas {

	/**
	 * The size margin to draw when margins are needed.
	 */
	private static final int MARGIN = 5;
	
	private static final String VERSION = "1.1";

	/**
	 * The default font to use for drawing the messages.
	 */
	private static final Font DEFAULT_SIMPLE_FONT = Font.getDefaultFont();

	private static final String[] aboutText = { "Mileage Calculator",
			"Version: " + VERSION, "Copyright (C) 2007", "Barry Redmond", "",
			"For more information visit:", "www.barryredmond.com" };

	private static final String[] featureText = { "If there are other features you think should be added to this Application, please use the above site to suggest them to me, and I will, hopefull, add them." };

	/**
	 * <p>
	 * The titles of the different sections
	 * </p>
	 * {@link AboutScreen#TITLES}[n] is the title corrosponding to
	 * {@link AboutScreen#MESSAGES}[n]<br>
	 * Both {@link AboutScreen#TITLES} and {@link AboutScreen#MESSAGES} must
	 * NOT be null, and must have the same number of elements.
	 */
	private static final String[] TITLES = { "About", "Useage" };

	/**
	 * <p>
	 * The text for the different sections
	 * </p>
	 * {@link AboutScreen#MESSAGES}[n] is the text corrosponding to
	 * {@link AboutScreen#TITLES}[n]<br>
	 * Both {@link AboutScreen#TITLES} and {@link AboutScreen#MESSAGES} must
	 * NOT be null, and must have the same number of elements.
	 */
	private static final String[][] MESSAGES = { aboutText, featureText };

	static {
		if (TITLES == null || MESSAGES == null
				|| TITLES.length != MESSAGES.length) {
			try {
				throw new java.lang.IllegalStateException(
						"There was a problem with the coding of the "
								+ AboutScreen.class.getName()
								+ " class. neither titles, nor messages may be null, and they both must have the same number of elements");
			} catch (IllegalStateException e) {
				e.printStackTrace();
				throw e;
			}
		}
	}

	private int yPos;

	// this is calculated the first time the paint(Graphics) method is
	// called.
	private int totalHeight;

	// Used to decide if we should set the 'totalHeight' property.
	private boolean firstTime = true;

	private String[][] formattedMessages;

	private Displayable previousScreen;

	/** Creates a new instance of AboutScreen */
	public AboutScreen(Displayable previous) {
		this.setFullScreenMode(true);
		this.previousScreen = previous;
		//this.setFullScreenMode(true);

		this.yPos = 0;

		this.formattedMessages = new String[MESSAGES.length][];
		for (int i = 0; i < MESSAGES.length; i++) {
			formattedMessages[i] = formatMessage(MESSAGES[i], this.getWidth());
		}
	}

	/**
	 * <p>
	 * Takes an array of messages and a 'Screen-width' and returns the same
	 * messages, but any string in that that is wider than 'width' will be
	 * split up into 2 or more Strings that will fit on the screen
	 * </p>
	 * 
	 * 'Spliting' up a String is done on the basis of Words, so if a single
	 * WORD is longer than 'width' it will be on a Line on it's own, but
	 * that line WILL be WIDER than 'width'
	 * 
	 * @param message
	 * @param width
	 *                the maximum width a string may be before being split
	 *                up.
	 * @return
	 */
	private String[] formatMessage(String[] message, int width) {
		Vector result = new Vector(message.length);
		for (int i = 0; i < message.length; i++) {
			if (DEFAULT_SIMPLE_FONT.stringWidth(message[i]) <= width) {
				result.addElement(message[i]);
			} else {
				String[] splitUp = StringUtil.chopStrings(message[i], " ",
						AboutScreen.DEFAULT_SIMPLE_FONT, width);
				for (int j = 0; j < splitUp.length; j++) {
					result.addElement(splitUp[j]);
				}
			}
		}

		String[] finalResult = new String[result.size()];
		for (int i = 0; i < finalResult.length; i++) {
			finalResult[i] = (String) result.elementAt(i);
		}
		return finalResult;

	}

	protected void paint(Graphics g) {
		int width = this.getWidth();

		// Fill in the background White
		g.setColor(0xFFFFFF); // White
		g.fillRect(0, 0, width, this.getHeight());

		int y = yPos;
		y += MARGIN;

		/*
		 if (this.logo != null) {
		 g.drawImage(this.logo, width / 2, y, Graphics.TOP
		 | Graphics.HCENTER);
		 y += logo.getHeight() + MARGIN;
		 }
		 */
		g.setColor(0x0); // Black

		// Write the title "About"
		final Font titleFont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD
				| Font.STYLE_UNDERLINED, Font.SIZE_LARGE);

		/*
		 * FIXME: currently paints ALL the text, even if there is (a lot) more
		 * than can fit on the screen. (must do this first time to assess
		 * 'height', but shouldn't need to do it for any other repaint
		 */
		for (int i = 0; i < TITLES.length; i++) {
			final int basicFontHeight = DEFAULT_SIMPLE_FONT.getHeight();
			final int titleFontHeight = titleFont.getHeight();
			// Write out the 'message' heading
			g.setFont(titleFont);
			final String title = TITLES[i];
			int stringWidth = g.getFont().stringWidth(title);
			g.drawString(title, (width - stringWidth) / 2, y, 0);
			y += titleFontHeight;

			// Write out the 'message' text.
			g.setFont(DEFAULT_SIMPLE_FONT);
			for (int j = 0; j < this.formattedMessages[i].length; j++) {
				final String message = this.formattedMessages[i][j];
				stringWidth = g.getFont().stringWidth(message);
				g.drawString(message, (width - stringWidth) / 2, y, 0);
				y += basicFontHeight;
			}
			y += basicFontHeight;
		}

		// Set the total-Height the first time
		if (firstTime) {
			totalHeight = y + MARGIN;
			firstTime = false;
		}
	}

	/** Handle all keyPressed-events */
	public void keyPressed(int keycode) {
		if (this.getGameAction(keycode) == UP) {
			upPressed();
		} else if (this.getGameAction(keycode) == DOWN) {
			downPressed();
		} else {
			// Exit on ANY other key press.
			Display.getDisplay(MileageMIDlet.getMileageMIDlet()).setCurrent(
					previousScreen);
		}
	}

	/** Handle all keyRepeaded-events */
	public void keyRepeated(int keycode) {
		if (this.getGameAction(keycode) == UP) {
			upPressed();
		} else if (this.getGameAction(keycode) == DOWN) {
			downPressed();
		}
	}

	/**
	 * <p>
	 * Pan the screen up if an Up-Key is pressed
	 * </p>
	 */
	private void upPressed() {
		yPos += 20;
		if (yPos > 0) {
			yPos = 0;
		}
		this.repaint();
	}

	/**
	 * <p>
	 * Pan the screen down if a Down-Key is pressed
	 * </p>
	 */
	private void downPressed() {
		yPos -= 20;
		if (yPos < this.getHeight() - this.totalHeight) {
			yPos = this.getHeight() - this.totalHeight;
		}
		this.repaint();
	}
}
